#!/usr/bin/env python

"""Namelist creator for RTM
"""

# Typically ignore this.
# pylint: disable=invalid-name

# Disable these because this is our standard setup
# pylint: disable=wildcard-import,unused-wildcard-import,wrong-import-position
# pylint: disable=multiple-imports
import os, shutil, sys

CIMEROOT = os.environ.get("CIMEROOT")
if CIMEROOT is None:
    raise SystemExit("ERROR: must set CIMEROOT environment variable")
sys.path.append(os.path.join(CIMEROOT, "scripts", "Tools"))

from standard_script_setup import *
from CIME.case import Case
from CIME.nmlgen import NamelistGenerator
from CIME.utils import expect
from CIME.buildnml import create_namelist_infile, parse_input

logger = logging.getLogger(__name__)

# pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements
####################################################################################
def _create_namelists(case, confdir, inst_string, infile, nmlgen, data_list_path):
####################################################################################
    """Write out the namelist for this component.

    Most arguments are the same as those for `NamelistGenerator`. The
    `inst_string` argument is used as a suffix to distinguish files for
    different instances. The `confdir` argument is used to specify the directory
    in which output files will be placed.
    """
    #----------------------------------------------------
    # Create config dictionary
    #----------------------------------------------------
    config = {}
    config['rtm_mode'] = case.get_value("RTM_MODE")
    config['rtm_flood_mode'] = case.get_value("RTM_FLOOD_MODE")
    config['clm_accelerated_spinup'] = case.get_value("CLM_ACCELERATED_SPINUP")
    config['rof_grid'] = case.get_value("ROF_GRID")
    config['lnd_grid'] = case.get_value("LND_GRID")
    config['rof_ncpl'] = case.get_value("ROF_NCPL")
    config["simyr"] = case.get_value("RTM_SIM_YEAR")
    config["compset"] = case.get_value("COMPSET")

    #----------------------------------------------------
    # Check for incompatible options.
    #----------------------------------------------------
    if config["rof_grid"] == "null" and config["rtm_mode"] != "NULL":
        expect(False, "ROF_GRID is null RTM_MODE not NULL")

    #----------------------------------------------------
    # Initialize namelist defaults
    #----------------------------------------------------
    nmlgen.init_defaults(infile, config)

    #----------------------------------------------------
    # Set values not obtained in the default settings
    #----------------------------------------------------

    run_type = case.get_value("RUN_TYPE")
    finidat_rtm = str(nmlgen.get_value("finidat_rtm"))
    if run_type == 'branch' or run_type == 'hybrid':
        run_refcase = case.get_value("RUN_REFCASE")
        run_refdate = case.get_value("RUN_REFDATE")
        run_tod = case.get_value("RUN_REFTOD")
        filename = "%s.rtm%s.r.%s-%s.nc" %(run_refcase, inst_string, run_refdate, run_tod)
        rundir = case.get_value("RUNDIR")
        if not os.path.exists(os.path.join(rundir, filename)):
            filename = "%s.rtm.r.%s-%s.nc" %(run_refcase, run_refdate, run_tod)

        if run_type == "hybrid":
            nmlgen.add_default("finidat_rtm", value=filename, ignore_abs_path=True)
        else:
            nmlgen.add_default("nrevsn_rtm", value=filename)
    elif finidat_rtm.strip() == '':
        nmlgen.set_value('finidat_rtm', value=' ')
    else:
        if nmlgen.get_default('finidat_rtm') == 'UNSET':
            nmlgen.add_default('finidat_rtm', value=' ', ignore_abs_path=True)
        else:
            nmlgen.add_default("finidat_rtm")

    ncpl_base_period = case.get_value('NCPL_BASE_PERIOD')
    if ncpl_base_period == 'hour':
        basedt = 3600
    elif ncpl_base_period == 'day':
        basedt = 3600 * 24
    elif ncpl_base_period == 'year':
        if case.get_value('CALENDAR') == 'NO_LEAP':
            basedt = 3600 * 24 * 365
        else:
            expect(False, "Invalid CALENDAR for NCPL_BASE_PERIOD %s " %ncpl_base_period)
    elif ncpl_base_period == 'decade':
        if case.get_value('CALENDAR') == 'NO_LEAP':
            basedt = 3600 * 24 * 365 * 10
        else:
            expect(False, "invalid NCPL_BASE_PERIOD NCPL_BASE_PERIOD %s " %ncpl_base_period)
    else:
        expect(False, "invalid NCPL_BASE_PERIOD NCPL_BASE_PERIOD %s " %ncpl_base_period)

    if basedt < 0:
        expect(False, "basedt invalid overflow for NCPL_BASE_PERIOD %s " %ncpl_base_period)

    rof_ncpl = case.get_value("ROF_NCPL")
    if basedt % rof_ncpl != 0:
        expect(False, "rof_ncpl %s doesn't divide evenly into basedt %s\n"
               %(rof_ncpl, basedt))
    else:
        rtm_tstep = basedt // rof_ncpl
    nmlgen.set_value("rtm_tstep", value=rtm_tstep)

    #----------------------------------------------------
    # Write output namelist
    #----------------------------------------------------
    namelist_file = os.path.join(confdir, "rof_in")
    nmlgen.write_output_file(namelist_file, data_list_path, groups=['rtm_inparm'])

###############################################################################
def buildnml(case, caseroot, compname):
###############################################################################
    """Build the namelist """

    # Build the component namelist
    if compname != "rtm":
        raise AttributeError

    srcroot = case.get_value("SRCROOT")
    rundir = case.get_value("RUNDIR")
    ninst = case.get_value("NINST_ROF")

    # Determine configuration directory
    confdir = os.path.join(caseroot, "Buildconf", "rtmconf")
    if not os.path.isdir(confdir):
        os.makedirs(confdir)

    #----------------------------------------------------
    # Construct the namelist generator
    #----------------------------------------------------
    # determine directory for user modified namelist_definitions.xml and namelist_defaults.xml
    user_xml_dir = os.path.join(caseroot, "SourceMods", "src.rtm")
    expect(os.path.isdir(user_xml_dir),
           "user_xml_dir %s does not exist "%user_xml_dir)

    # NOTE: User definition *replaces* existing definition.
    namelist_xml_dir = os.path.join(srcroot, "components", "rtm", "cime_config")
    definition_file = [os.path.join(namelist_xml_dir, "namelist_definition_rtm.xml")]
    user_definition = os.path.join(user_xml_dir, "namelist_definition_rtm.xml")
    if os.path.isfile(user_definition):
        definition_file = [user_definition]
    for file_ in definition_file:
        expect(os.path.isfile(file_), "Namelist XML file %s not found!" % file_)

    # Create the namelist generator object - independent of instance
    nmlgen = NamelistGenerator(case, definition_file)

    #----------------------------------------------------
    # Clear out old data.
    #----------------------------------------------------
    data_list_path = os.path.join(case.get_case_root(), "Buildconf", "rtm.input_data_list")
    if os.path.exists(data_list_path):
        os.remove(data_list_path)
    #----------------------------------------------------
    # Loop over instances
    #----------------------------------------------------
    for inst_counter in range(1, ninst+1):

        # determine instance string
        inst_string = ""
        if ninst > 1:
            inst_string = '_' + '%04d' % inst_counter

        # If multi-instance case does not have restart file, use
        # single-case restart for each instance
        rpointer = "rpointer.rof"
        if (os.path.isfile(os.path.join(rundir, rpointer)) and
                (not os.path.isfile(os.path.join(rundir, rpointer + inst_string)))):
            shutil.copy(os.path.join(rundir, rpointer),
                        os.path.join(rundir, rpointer + inst_string))

        inst_string_label = inst_string
        if not inst_string_label:
            inst_string_label = "\"\""

        # create namelist output infile using user_nl_file as input
        user_nl_file = os.path.join(caseroot, "user_nl_rtm" + inst_string)
        expect(os.path.isfile(user_nl_file),
               "Missing required user_nl_file %s " %(user_nl_file))
        infile = os.path.join(confdir, "namelist_infile")
        create_namelist_infile(case, user_nl_file, infile)
        namelist_infile = [infile]

        # create namelist
        _create_namelists(case, confdir, inst_string, namelist_infile, nmlgen, data_list_path)

        # copy namelist files and stream text files, to rundir
        if os.path.isdir(rundir):
            file_src = os.path.join(confdir, 'rof_in')
            file_dest = os.path.join(rundir, 'rof_in')
            if inst_string:
                file_dest += inst_string
            shutil.copy(file_src, file_dest)

            for txtfile in glob.glob(os.path.join(confdir, "*txt*")):
                shutil.copy(txtfile, rundir)

###############################################################################
def _main_func():

    caseroot = parse_input(sys.argv)
    with Case(caseroot) as case:
        buildnml(case, caseroot, "rtm")

if __name__ == "__main__":
    _main_func()
